package com.sunwayworld.basemodule.common.utils;

import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.config.GramerSymbol;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.PictureRenderPolicy;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTAnchor;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
import java.util.Set;
import java.util.function.Function;

public class ExportUtil {

    public static void build(InputStream templateFile, Function<ConfigureBuilder, Object> paramsBuilder, OutputStream outputConsumer) throws IOException {

        ConfigureBuilder builder = Configure.builder();
        builder.buildGramer("${", "}");
        //builder.addPlugin('@', new MyPictureRenderPolicy());
        builder.bind("mergeCellsVertically", new MergeCellsVertically());
        builder.useSpringEL();
        // 处理文本中的上下标
        builder.addPlugin(GramerSymbol.TEXT.getSymbol(), new LimsTextRenderPolicy());// 文字处理
        XWPFTemplate template = XWPFTemplate.compile(templateFile, builder.build()).render(paramsBuilder.apply(builder));
        try {
            template.write(outputConsumer);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                template.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    private static ByteArrayOutputStream cloneInputStream(InputStream input) {
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len;
            while ((len = input.read(buffer)) > -1) {
                baos.write(buffer, 0, len);
            }
            baos.flush();
            return baos;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static byte[] toByteArray(InputStream input) {
        try (ByteArrayOutputStream output = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            for (int n; -1 != (n = input.read(buffer)); ) {
                output.write(buffer, 0, n);
            }
            return output.toByteArray();
        } catch (Exception e) {
            try {
                input.close();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

    public static class MergeCellsVertically implements RenderPolicy {

        private ThreadLocal<Set<String>> mergeCellMark = new ThreadLocal<>();

        @Override
        public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
            RunTemplate runTemplate = (RunTemplate) eleTemplate;
            XWPFRun run = runTemplate.getRun();
            run.setText("", 0);
            try {
                if (!TableTools.isInsideTable(run)) {
                    throw new IllegalStateException(
                            "合并列单元格的模板标签${mergeCellsVertically}" + runTemplate.getSource() + "必须放在table中");
                }
                XWPFTableCell cell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();
                String text = cell.getText();

                CTTcPr tcPr = cell.getCTTc().isSetTcPr() ? cell.getCTTc().getTcPr() : cell.getCTTc().addNewTcPr();
                CTVMerge vMerge = tcPr.addNewVMerge();
                if(mergeCellMark.get() == null) {
                    mergeCellMark.set(new HashSet<>());
                }
                if (!mergeCellMark.get().contains(text)) {
                    // The first merged cell is set with RESTART merge value
                    vMerge.setVal(STMerge.RESTART);
                    mergeCellMark.get().add(text);
                } else {
                    // Cells which join (merge) the first one, are set with CONTINUE
                    vMerge.setVal(STMerge.CONTINUE);
                }

            } catch (Exception e) {
                throw new RenderException("合并列单元格错误:" + e.getMessage(), e);
            }
        }
    }

    private static int getColNum(XWPFTableCell cell) {

        int colNum = 0;
        XWPFTableRow row = cell.getTableRow();
        List<XWPFTableCell> cells = row.getTableCells();
        for (int i = 0; i < cells.size(); i++) {
            XWPFTableCell tableCell = cells.get(i);
            if (tableCell.getCTTc() == cell.getCTTc()) {
                colNum = i + 1;
            }
        }

        return colNum;
    }

    private static int getRowNum(XWPFTableRow row) {

        XWPFTable table = row.getTable();
        int rowNum = 0;
        List<XWPFTableRow> rows = table.getRows();
        for (int i = 0; i < rows.size(); i++) {
            XWPFTableRow tableRow = rows.get(i);
            if(tableRow.getCtRow() == row.getCtRow()) {
                rowNum = i + 1;
            }
        }

        return rowNum;
    }
}
